package ypmits.physics {
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;

	/**
	 * @author Dave & Rens
	 */
	public class BoxOnRopesMotion extends Sprite {

		private var original_ropes_positions : Array = [];
		private var original_box_position : Array;
		
		private var _ropes : Array;
		private var _ropeAngles : Array;
		private var _box : DisplayObject;
		private var _ropeSwingSpeed : Number = 0;
		private var _boxSwingSpeed : Number = 0;
		private var _swingAngle : Number = 0;
		private var _boxRadius : Number;
		private var _boxHingeX : Number;
		private var _boxHingeY : Number;
		private var _friction : Number;
		private var _weight : Number;

		
		public function BoxOnRopesMotion( ropes : Array, box : DisplayObject, weight : Number = 1000, friction : Number = 100 ) {
			_ropes = ropes;
			_box = box;
			
			for (var i : int = 0; i < ropes.length; i++) {
				var r : DisplayObject = ropes[i];
				original_ropes_positions[i] = [];
				original_ropes_positions[i]['push']( r.x, r.y );
			}
			
			original_box_position = [ _box.x, _box.y ];
			
			_ropeAngles = new Array( );
			
			_weight = weight;
			_friction = friction;

			_boxHingeX = 0;
			_boxHingeY = 0;
			
			for ( var counter : Number = 0; counter < _ropes.length; counter++ ) {
				var rope : DisplayObject = DisplayObject( _ropes[counter] );
				_boxHingeX += rope.x;
				_boxHingeY += rope.y;
				
				_ropeAngles[counter] = rope.rotation;
			}
				
			_boxHingeX /= _ropes.length;
			_boxHingeY /= _ropes.length;
				
			_boxRadius = _box.y - _boxHingeY;
		}

		
		public function set ropeRotation( newRotation : Number ) : void {
			_swingAngle = newRotation;
			gravityTick( );
		}

		
		public function get ropeRotation() : Number {
			return _swingAngle;
		}

		
		public function set swingSpeed(newSpeed : Number) : void {
			_ropeSwingSpeed = (_ropeSwingSpeed + newSpeed) / 2;
		}

		
		public function get swingSpeed() : Number {
			return _ropeSwingSpeed;
		}

		
		public function start() : void {
			addEventListener( Event.ENTER_FRAME, gravityTick );
		}

		
		public function stop() : void {
			removeEventListener( Event.ENTER_FRAME, gravityTick );
		}

		
		private function gravityTick(e : Event = null) : void {
			_ropeSwingSpeed -= (_swingAngle / 5);
			_ropeSwingSpeed /= (1.05 + (_weight / 5000));
			_swingAngle += _ropeSwingSpeed;
			
			for (var c : Number = 0; c < _ropes.length; c++) {
				DisplayObject( _ropes[c] ).rotation = _swingAngle + _ropeAngles[c];
			}
			
			if (_ropes.length < 2) {
				_boxSwingSpeed -= ((_ropeSwingSpeed - (_box.rotation - _swingAngle)) / 8);
				_boxSwingSpeed /= 1.05 + (_friction / 100);
				_box.rotation -= _boxSwingSpeed;
			}
			
			_box.x = original_box_position[0] + ( _boxHingeX + Math.sin( (0 - _swingAngle) / 180 * Math.PI ) * _boxRadius );
			_box.y = ( _boxHingeY + Math.cos( (0 - _swingAngle) / 180 * Math.PI ) * _boxRadius );
		}
	}
}
